package com.moter.demo01.rpc;



import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * selector直接调用底层，不用再内核和程序直接往返。
 */
public class SocketSingleWithSelectorIO {
    private Selector selector = null;
    private ServerSocketChannel server =null;
    private int port;
    //初始化服务端
    public void initSever(){
        try {
            port=9090;
            server=ServerSocketChannel.open();
            server.bind(new InetSocketAddress(port));
            server.configureBlocking(false);
            selector =  Selector.open();//多路多复用器启动
            server.register(selector, SelectionKey.OP_ACCEPT);//注册到复用器，监听客户端的连接
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //开始
    public void start(){
        initSever();
        System.out.println("服务器启动了");
        try {
            while(true){
                while (selector.select(0)>0){
                    Set<SelectionKey> selectionKeys = selector.selectedKeys();//获得所有事件
                    Iterator<SelectionKey> iterator = selectionKeys.iterator();//获得迭代器
                    while(iterator.hasNext()){//迭代
                        SelectionKey next = iterator.next();
                        iterator.remove();//移除，防止多次读
                        if(next.isAcceptable()){//如果是新客户端
                            acceptHandler(next);//把新客户端 注册进入多路复用器
                        }else if(next.isReadable()){//如果是消息
                            readHandler(next);//读取信息。
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void readHandler(SelectionKey next) {
        SocketChannel client = (SocketChannel)next.channel();
        ByteBuffer byteBuffer=(ByteBuffer)next.attachment();
        byteBuffer.clear();
        int read=0;
        try {
            while(true){
                read=client.read(byteBuffer);
                System.out.println(read);
                if(read>0){
                    byteBuffer.flip();
                    while(byteBuffer.hasRemaining()){
                        byte[] data = new byte[byteBuffer.limit()];
                        byteBuffer.get(data);
                        System.out.println(new String(data));
                        ByteBuffer allocate = ByteBuffer.allocateDirect(4096);
                        String data1 = "我是你爹\n";
                        allocate.put(data1.getBytes());
                        allocate.flip();
                        client.write(allocate);
                        allocate.clear();
                    }
                    byteBuffer.clear();
                }else if(read==0){
                    break;
                }else {
                    client.close();
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void acceptHandler(SelectionKey next) {
        ServerSocketChannel channel = (ServerSocketChannel)next.channel();

        try {
            SocketChannel client = channel.accept();//获取连接
            client.configureBlocking(false);//设置为非阻塞
            ByteBuffer byteBuffer = ByteBuffer.allocate(8192);//设置缓冲区buffer 堆内
            client.register(selector,SelectionKey.OP_READ,byteBuffer);//注册进入多路复用器
            System.out.println("================================");
            System.out.println("新客户端连接"+client.getRemoteAddress());
            System.out.println("================================");
        } catch (ClosedChannelException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new SocketSingleWithSelectorIO().start();
    }
}
